package com.atjava.nebula.core.util.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang.StringUtils;

import com.atjava.nebula.core.constant.Constant;
import com.atjava.nebula.core.constant.ProjectConstant;
import com.atjava.nebula.core.exception.baseExp.SystemException;

public class ReflectUtil {

	/**通过反射向对象里动态填充值
	 * @param target 要填充值的对象
	 * @param fname	填充的属性名
	 *  @param ftype 填充属性的类型
	 * @param fvalue	填充的值
	 */	
	@SuppressWarnings("unchecked")
	public static void setFieldValue(Object target, String fname, Class ftype,
			Object fvalue) throws SystemException{

		if (target == null
				|| fname == null
				|| "".equals(fname)
				|| (fvalue != null && !ftype
						.isAssignableFrom(fvalue.getClass()))) {

			return;
		}
		Class clazz = target.getClass();
		try {
			Method method = clazz.getDeclaredMethod("set"
					+ fname.substring(0, 1).toUpperCase() + fname.substring(1),
					ftype);
			if (!Modifier.isPublic(method.getModifiers())) {
				method.setAccessible(true);
			}
			method.invoke(target, fvalue);

		} catch (Exception me) {

			try {
				Field field = clazz.getDeclaredField(fname);
				if (!Modifier.isPublic(field.getModifiers())) {
					field.setAccessible(true);
				}
				field.set(target, fvalue);
			} catch (Exception fe) {
				throw new SystemException(fe, "通过反射向对象里动态填充值时出错") ;
			}
		}
	}
	
	/**通过反射向对象里动态填充值
	 * @param object 要填充值的对象
	 * @param fname	填充的属性名
	 * @param fvalue	填充的值
	 */
	public static void setFieldValue(Object object, String fname, String fvalue) throws SystemException {
		if(StringUtils.isBlank(fvalue))
			return ;
		try {
			Field field = object.getClass().getDeclaredField(fname);
			//object.getClass().getd
			boolean isFoolback = false;
			if (field.isAccessible() == false) {
				isFoolback = true;
				field.setAccessible(true);
			}

			if (field.getType() == int.class) {
				field.setInt(object, Integer.parseInt(fvalue));
			} else if (field.getType() == Integer.class) {
				field.set(object, Integer.valueOf(fvalue));

			} else if (field.getType() == long.class) {
				field.setLong(object, Long.parseLong(fvalue));
			} else if (field.getType() == Long.class) {
				field.set(object, Long.valueOf(fvalue));

			} else if (field.getType() == float.class) {
				field.setFloat(object, Float.parseFloat(fvalue));
			} else if (field.getType() == Float.class) {
				field.set(object, Float.valueOf(fvalue));

			} else if (field.getType() == double.class) {
				field.setDouble(object, Double.parseDouble(fvalue));
			} else if (field.getType() == Double.class) {
				field.set(object, Double.valueOf(fvalue));

			} else if (field.getType() == short.class) {
				field.setShort(object, Short.parseShort(fvalue));
			} else if (field.getType() == Short.class) {
				field.set(object, Short.valueOf(fvalue));

			} else if (field.getType() == byte.class) {
				field.setByte(object, Byte.parseByte(fvalue));
			} else if (field.getType() == Byte.class) {
				field.set(object, Byte.valueOf(fvalue));

			} else if (field.getType() == boolean.class) {
				field.setBoolean(object, Boolean.parseBoolean(fvalue));
			} else if (field.getType() == Boolean.class) {
				field.set(object, Boolean.valueOf(fvalue));

			} else if (field.getType() == BigDecimal.class) {
				field.set(object, BigDecimal
						.valueOf(Double.parseDouble(fvalue)));

			} else if (field.getType() == Date.class) {
				field.set(object, new SimpleDateFormat(Constant.DEFAULT_TIME_FORMAT).parseObject(fvalue));

			} else {
				field.set(object, fvalue);// String   
				//field.get
			}
			if (isFoolback) {
				field.setAccessible(false);
			}
		} catch (Exception e) {
			throw new SystemException(e, "通过反射向对象里动态填充值时出错") ;
		}

	}
	
	public static Object getFieldValue(Object object, String fname) throws SystemException {

		Object value=null;
		try {
			Field field = object.getClass().getDeclaredField(fname);
			//object.getClass().getd
			boolean isFoolback = false;
			if (field.isAccessible() == false) {
				isFoolback = true;
				field.setAccessible(true);
			}
			value=field.get(object);
			if (isFoolback) {
				field.setAccessible(false);
			}
		} catch (Exception e) {
			throw new SystemException(e, "Get property ["+fname+"] from object ["+object+"]. ") ;		
		}
		return value;
	}	
}
